package com.acerola.mrpc.protocol;

import com.acerola.mrpc.constant.ReqType;
import com.acerola.mrpc.constant.RpcConstant;
import com.acerola.mrpc.message.RpcProtocol;
import com.acerola.mrpc.message.RpcRequest;
import com.acerola.mrpc.message.RpcResponse;
import com.acerola.mrpc.serializer.ISerializer;
import com.acerola.mrpc.serializer.SerializerManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @program: mrpc
 * @description: 编解码器
 * @author: Acerola
 * @create: 2022-12-10 20:33
 **/
@Slf4j
@ChannelHandler.Sharable
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, RpcProtocol<Object>> {
    /**
     * 编码
     *
     * @param ctx
     * @param rpcProtocol
     * @param list
     * @throws Exception
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, RpcProtocol<Object> rpcProtocol, List<Object> list) throws Exception {
        log.debug("========begin RpcEecoder==========");
        ByteBuf buffer = ctx.alloc().buffer();
        Header header = rpcProtocol.getHeader();
        //写入header
        buffer.writeShort(header.getMagic());
        buffer.writeByte(header.getVersion());
        buffer.writeByte(header.getSerializeType());
        buffer.writeByte(header.getMessageType());
        buffer.writeLong(header.getRequestId());
        //写入内容
        ISerializer serializer = SerializerManager.getSerializer(header.getSerializeType());
        byte[] serialize = serializer.serialize(rpcProtocol.getContent());
        buffer.writeInt(serialize.length);
        buffer.writeBytes(serialize);
        list.add(buffer);
    }

    /**
     * 解码
     *
     * @param ctx
     * @param byteBuf
     * @param list
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {
        log.debug("========begin RpcDecoder==========");

        if (byteBuf.readableBytes() < RpcConstant.HEAD_TOTAL_LEN) {
            return;
        }
        short magic = byteBuf.readShort();
        byte version = byteBuf.readByte();
        byte serializeType = byteBuf.readByte();
        byte messageType = byteBuf.readByte();
        long requestId = byteBuf.readLong();
        int length = byteBuf.readInt();
        byte[] bytes = new byte[length];
        //写入byte数组
        byteBuf.readBytes(bytes);
        Header header = new Header(magic, version, serializeType, messageType, requestId, length);
        //获取消息类型
        ReqType type = ReqType.findByCode(messageType);
        //获取序列化方式
        ISerializer serializer = SerializerManager.getSerializer(serializeType);
        switch (type) {
            case REQUEST -> {
                RpcRequest request = serializer.deserialize(RpcRequest.class, bytes);
                RpcProtocol<RpcRequest> rpcRequestRpcProtocol = new RpcProtocol<>();
                rpcRequestRpcProtocol.setHeader(header);
                rpcRequestRpcProtocol.setContent(request);
                list.add(rpcRequestRpcProtocol);
            }
            case RESPONSE -> {
                RpcResponse response = serializer.deserialize(RpcResponse.class, bytes);
                RpcProtocol<RpcResponse> rpcResppcP = new RpcProtocol<>();
                rpcResppcP.setHeader(header);
                rpcResppcP.setContent(response);
                list.add(rpcResppcP);
            }
            case HEARTBEAT -> {
                //TODO
                break;
            }
            default -> throw new Exception();
        }

    }
}
